﻿using System;
using System.Net;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

using Pacem.Silverlight.Tweening;
using Pacem.Silverlight.Tweening.Easing;
using System.Collections.Generic;

namespace CurveMenuPanel
{
    public class CurveMenuPanel : Control
    {
        bool IsInit = false;


        #region Curvature (DependencyProperty)  曲率

        private double _curvature = 20.0;

        /// <summary>
        /// A description of the property.
        /// </summary>
        public double Curvature
        {
            get { return (double)GetValue(CurvatureProperty); }
            set { SetValue(CurvatureProperty, value); }
        }
        public static readonly DependencyProperty CurvatureProperty =
            DependencyProperty.Register("Curvature", typeof(double), typeof(CurveMenuPanel),
            new PropertyMetadata(20.0, new PropertyChangedCallback(OnCurvatureChanged)));

        private static void OnCurvatureChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CurveMenuPanel)d).OnCurvatureChanged(e);
        }

        protected virtual void OnCurvatureChanged(DependencyPropertyChangedEventArgs e)
        {
            _curvature = (double)e.NewValue;
            size();
        }

        #endregion

        #region CurrentPosition (DependencyProperty)

        public double _currentPosition = 0;

        /// <summary>
        /// currentPosition
        /// </summary>
        public double CurrentPosition
        {
            get { return (double)GetValue(CurrentPositionProperty); }
            set { SetValue(CurrentPositionProperty, value); }
        }
        public static readonly DependencyProperty CurrentPositionProperty =
            DependencyProperty.Register("CurrentPosition", typeof(double), typeof(CurveMenuPanel),
            new PropertyMetadata(0.0, new PropertyChangedCallback(OnCurrentPositionChanged)));

        private static void OnCurrentPositionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CurveMenuPanel)d).OnCurrentPositionChanged(e);
        }

        protected virtual void OnCurrentPositionChanged(DependencyPropertyChangedEventArgs e)
        {
            _currentPosition = (double)e.NewValue;
        }

        #endregion

        #region ItemDistance (DependencyProperty)   间距

        private double _itemDistance = 70;

        /// <summary>
        /// 间距
        /// </summary>
        public double ItemDistance
        {
            get { return (double)GetValue(ItemDistanceProperty); }
            set { SetValue(ItemDistanceProperty, value); }
        }
        public static readonly DependencyProperty ItemDistanceProperty =
            DependencyProperty.Register("ItemDistance", typeof(double), typeof(CurveMenuPanel),
            new PropertyMetadata(70.0, new PropertyChangedCallback(OnItemDistanceChanged)));

        private static void OnItemDistanceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CurveMenuPanel)d).OnItemDistanceChanged(e);
        }

        protected virtual void OnItemDistanceChanged(DependencyPropertyChangedEventArgs e)
        {
            _itemDistance = (double)e.NewValue;
            size();
        }

        #endregion

        #region MiddleItemDistance (DependencyProperty) 中间间距

        private double _middleItemDistance = 150;

        /// <summary>
        /// 中间间距
        /// </summary>
        public double MiddleItemDistance
        {
            get { return (double)GetValue(MiddleItemDistanceProperty); }
            set { SetValue(MiddleItemDistanceProperty, value); }
        }
        public static readonly DependencyProperty MiddleItemDistanceProperty =
            DependencyProperty.Register("MiddleItemDistance", typeof(double), typeof(CurveMenuPanel),
            new PropertyMetadata(150.0, new PropertyChangedCallback(OnMiddleItemDistanceChanged)));

        private static void OnMiddleItemDistanceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CurveMenuPanel)d).OnMiddleItemDistanceChanged(e);
        }

        protected virtual void OnMiddleItemDistanceChanged(DependencyPropertyChangedEventArgs e)
        {
            _middleItemDistance = (double)e.NewValue;
            size();
        }

        #endregion

        #region MiddleItemScale (DependencyProperty)

        private double _middleItemScale = 1.5;

        /// <summary>
        /// MiddleItemScale
        /// </summary>
        public double MiddleItemScale
        {
            get { return (double)GetValue(MiddleItemScaleProperty); }
            set { SetValue(MiddleItemScaleProperty, value); }
        }
        public static readonly DependencyProperty MiddleItemScaleProperty =
            DependencyProperty.Register("MiddleItemScale", typeof(double), typeof(CurveMenuPanel),
            new PropertyMetadata(1.5, new PropertyChangedCallback(OnMiddleItemScaleChanged)));

        private static void OnMiddleItemScaleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CurveMenuPanel)d).OnMiddleItemScaleChanged(e);
        }

        protected virtual void OnMiddleItemScaleChanged(DependencyPropertyChangedEventArgs e)
        {
            _middleItemScale = (double)e.NewValue;
        }

        #endregion

        #region ItemScaleRatio (DependencyProperty)

        private double _itemScaleRatio = 0.5;

        /// <summary>
        /// ItemScaleRatio
        /// </summary>
        public double ItemScaleRatio
        {
            get { return (double)GetValue(ItemScaleRatioProperty); }
            set { SetValue(ItemScaleRatioProperty, value); }
        }
        public static readonly DependencyProperty ItemScaleRatioProperty =
            DependencyProperty.Register("ItemScaleRatio", typeof(double), typeof(CurveMenuPanel),
            new PropertyMetadata(0.5, new PropertyChangedCallback(OnItemScaleRatioChanged)));

        private static void OnItemScaleRatioChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CurveMenuPanel)d).OnItemScaleRatioChanged(e);
        }

        protected virtual void OnItemScaleRatioChanged(DependencyPropertyChangedEventArgs e)
        {
            _itemScaleRatio = (double)e.NewValue;
        }

        #endregion

        #region ItemAlpha (DependencyProperty)

        private double _itemAlpha = 0.51;

        /// <summary>
        /// ItemAlpha
        /// </summary>
        public double ItemAlpha
        {
            get { return (double)GetValue(ItemAlphaProperty); }
            set { SetValue(ItemAlphaProperty, value); }
        }
        public static readonly DependencyProperty ItemAlphaProperty =
            DependencyProperty.Register("ItemAlpha", typeof(double), typeof(CurveMenuPanel),
            new PropertyMetadata(0.51, new PropertyChangedCallback(OnItemAlphaChanged)));

        private static void OnItemAlphaChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CurveMenuPanel)d).OnItemAlphaChanged(e);
        }

        protected virtual void OnItemAlphaChanged(DependencyPropertyChangedEventArgs e)
        {
            _itemAlpha = (double)e.NewValue;
        }

        #endregion

        #region ItemWidth (DependencyProperty)

        private double _itemWidth = 75;

        /// <summary>
        /// A description of the property.
        /// </summary>
        public double ItemWidth
        {
            get { return (double)GetValue(ItemWidthProperty); }
            set { SetValue(ItemWidthProperty, value); }
        }
        public static readonly DependencyProperty ItemWidthProperty =
            DependencyProperty.Register("ItemWidth", typeof(double), typeof(CurveMenuPanel),
            new PropertyMetadata(75.0, new PropertyChangedCallback(OnItemWidthChanged)));

        private static void OnItemWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CurveMenuPanel)d).OnItemWidthChanged(e);
        }

        protected virtual void OnItemWidthChanged(DependencyPropertyChangedEventArgs e)
        {
            _itemWidth = (double)e.NewValue;
            size();
        }

        #endregion

        #region CaptionEnabled (DependencyProperty)

        /// <summary>
        /// A description of the property.
        /// </summary>
        public bool CaptionEnabled
        {
            get { return (bool)GetValue(CaptionEnabledProperty); }
            set { SetValue(CaptionEnabledProperty, value); }
        }
        public static readonly DependencyProperty CaptionEnabledProperty =
            DependencyProperty.Register("CaptionEnabled", typeof(bool), typeof(CurveMenuPanel),
            new PropertyMetadata(true, new PropertyChangedCallback(OnCaptionEnabledChanged)));

        private static void OnCaptionEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CurveMenuPanel)d).OnCaptionEnabledChanged(e);
        }

        protected virtual void OnCaptionEnabledChanged(DependencyPropertyChangedEventArgs e)
        {
            size();
        }

        #endregion

        #region CaptionDistance (DependencyProperty)

        /// <summary>
        /// A description of the property.
        /// </summary>
        public double CaptionDistance
        {
            get { return (double)GetValue(CaptionDistanceProperty); }
            set { SetValue(CaptionDistanceProperty, value); }
        }
        public static readonly DependencyProperty CaptionDistanceProperty =
            DependencyProperty.Register("CaptionDistance", typeof(double), typeof(CurveMenuPanel),
            new PropertyMetadata(0.0, new PropertyChangedCallback(OnCaptionDistanceChanged)));

        private static void OnCaptionDistanceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CurveMenuPanel)d).OnCaptionDistanceChanged(e);
        }

        protected virtual void OnCaptionDistanceChanged(DependencyPropertyChangedEventArgs e)
        {
            size();
        }

        #endregion

        #region InfiniteScrollEnabled (DependencyProperty)

        private bool _infiniteScrollEnabled = true;

        /// <summary>
        /// A description of the property.
        /// </summary>
        public bool InfiniteScrollEnabled
        {
            get { return (bool)GetValue(InfiniteScrollEnabledProperty); }
            set { SetValue(InfiniteScrollEnabledProperty, value); }
        }
        public static readonly DependencyProperty InfiniteScrollEnabledProperty =
            DependencyProperty.Register("InfiniteScrollEnabled", typeof(bool), typeof(CurveMenuPanel),
            new PropertyMetadata(true, new PropertyChangedCallback(OnInfiniteScrollEnabledChanged)));

        private static void OnInfiniteScrollEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CurveMenuPanel)d).OnInfiniteScrollEnabledChanged(e);
        }

        protected virtual void OnInfiniteScrollEnabledChanged(DependencyPropertyChangedEventArgs e)
        {
            _infiniteScrollEnabled = (bool)e.NewValue;
            size();
        }

        #endregion

        #region CurrItemData (DependencyProperty)

        /// <summary>
        /// A description of the property.
        /// </summary>
        public ItemData CurrItemData
        {
            get { return (ItemData)GetValue(CurrItemDataProperty); }
            set { SetValue(CurrItemDataProperty, value); }
        }
        public static readonly DependencyProperty CurrItemDataProperty =
            DependencyProperty.Register("CurrItemData", typeof(ItemData), typeof(CurveMenuPanel),
            new PropertyMetadata(null, new PropertyChangedCallback(OnCurrItemDataChanged)));

        private static void OnCurrItemDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CurveMenuPanel)d).OnCurrItemDataChanged(e);
        }

        protected virtual void OnCurrItemDataChanged(DependencyPropertyChangedEventArgs e)
        {
        }

        #endregion


        #region RoationY (DependencyProperty)

        /// <summary>
        /// A description of the property.
        /// </summary>
        public double RoationY
        {
            get { return (double)GetValue(RoationYProperty); }
            set { SetValue(RoationYProperty, value); }
        }
        public static readonly DependencyProperty RoationYProperty =
            DependencyProperty.Register("RoationY", typeof(double), typeof(CurveMenuPanel),
            new PropertyMetadata(60.0, new PropertyChangedCallback(OnRoationYChanged)));

        private static void OnRoationYChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CurveMenuPanel)d).OnRoationYChanged(e);
        }

        protected virtual void OnRoationYChanged(DependencyPropertyChangedEventArgs e)
        {
            max_roationy = (double)e.NewValue;
        }

        #endregion


        #region

        private int _itemCount = 11;
        protected bool _captionEnabled = true;
        protected bool _captionPersisted = true;
        private int _tailItemIndex = 0;
        private double BASE_ROTATION = 0;
        private double TIME_LIMIT_L = 0;
        private double TIME_LIMIT_R = 0;
        private double SIDE_ROTATION = 0;

        private double max_roationy = 60;

        private int _headItemIndex = 0;
        private double BASE_RADIUS = 0;

        private double _mouseDownPosition = 0;
        protected string _captionSkin = "";
        private double MIDDLE_ROTATION = 0;
        private Container _container;
        private int _oddItemCount = 5;
        private double _transitionTime = 1.5;
        private double _mouseDownX = 0;
        private double _mouseDownY = 0;


        protected double _itemIndexLimitL = 0;
        protected double _itemIndexLimitR = 0;
        protected double _currentItemIndex = 0;


        public List<ItemData> itemDataList;

        private double width = 4;
        private double height = 3;


        private List<CurveMenuItem> _screenObjectList;


        private CurveMenuItem _currentItem;
        protected int _direction = 1;

        #endregion

        Canvas LayoutRoot;

        public CurveMenuPanel()
            : base()
        {
           
            DefaultStyleKey = typeof(CurveMenuPanel);
        }



        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            LayoutRoot = this.GetTemplateChild<Canvas>("LayoutRoot");
            init();
            IsInit = true;
        }

        private T GetTemplateChild<T>(string childName) where T : DependencyObject
        {
            T childControl = this.GetTemplateChild(childName) as T;
            if (childControl == null)
            {
                throw new Exception(string.Format("Couldn't find {0}", childName));
            }
            return childControl;
        }



        protected void init()
        {
            _container = new Container();
            LayoutRoot.Children.Add(_container);
        }

        public void buildScreen()
        {
            var i = 0;

            _headItemIndex = (itemDataList.Count - 1) - _oddItemCount;
            if (_headItemIndex < 0)
            {
                _headItemIndex = (itemDataList.Count + _headItemIndex) % itemDataList.Count;
            }
            _tailItemIndex = itemDataList.Count - _oddItemCount;
            if (_tailItemIndex < 0)
            {
                _tailItemIndex = (itemDataList.Count + _tailItemIndex) % itemDataList.Count;
            }
            _screenObjectList = new List<CurveMenuItem>();

            for (i = 0; i < _itemCount; i++)
            {

                var cmi = new CurveMenuItem(i);
                var itemData = itemDataList[_tailItemIndex];
                    cmi.MyItemData = itemData;

                if (!_infiniteScrollEnabled && i - _oddItemCount < 0)
                {
                    cmi.visible = false;
                }

                cmi.MouseLeftButtonUp += new MouseButtonEventHandler(cmi_MouseLeftButtonUp);

                _screenObjectList.Add(cmi);



                _container.addChildAt(cmi, 0);

                if (_tailItemIndex < (itemDataList.Count - 1))
                {
                    _tailItemIndex++;
                    continue;
                }
                _tailItemIndex = 0;
            }

            size();

            CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
        }

        void cmi_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            CurveMenuItem cmi = sender as CurveMenuItem;
            moveToItem(cmi.pos - _oddItemCount);
        }

        protected void size()
        {
            var i = 0;
            if (_curvature == 0)
            {
            }
            else
            {
                BASE_RADIUS = 100 / Math.Abs(_curvature) * ((_oddItemCount - 1) * _itemDistance + _middleItemDistance) / Math.PI * 0.5;
            }
            BASE_ROTATION = Math.PI * 2 * Math.Abs(_curvature) / 100;
            MIDDLE_ROTATION = BASE_ROTATION * 0.5 / ((_oddItemCount - 1) * _itemDistance + _middleItemDistance) * _middleItemDistance;
            SIDE_ROTATION = BASE_ROTATION * 0.5 / ((_oddItemCount - 1) * _itemDistance + _middleItemDistance) * _itemDistance;
            TIME_LIMIT_L = _oddItemCount - 1;
            TIME_LIMIT_R = _oddItemCount + 1;
            _container.x = width / 2;
            if (_curvature > 0)
            {
                _container.rotation = (-BASE_ROTATION) / Math.PI * 90;
                _container.y = height / 2 + BASE_RADIUS;
            }
            else if (_curvature < 0)
            {
                _container.rotation = BASE_ROTATION / Math.PI * 90 + 180;
                _container.y = height / 2 - BASE_RADIUS;
            }
            else
            {
                _container.rotation = 0;
                _container.y = height / 2;
            }
            _itemIndexLimitL = Math.Round(_currentPosition) - _currentItemIndex;
            _itemIndexLimitR = Math.Round(_currentPosition) + (itemDataList.Count - _currentItemIndex);


            for (i = 0; i < _itemCount; i++)
            {
                var cmi = _screenObjectList[i];
                if (cmi.IsInit)
                {
                    var position = getPosition(cmi.pos - _currentPosition);
                    cmi.Scale = position.s;
                    cmi.rotation = position.r;
                    cmi.x = position.x;
                    cmi.y = position.y;
                    cmi.alpha = position.a;
                    cmi.ItemWitch = _itemWidth;
                    cmi.CaptionEnabled = CaptionEnabled;
                    cmi.CaptionDistance = CaptionDistance;

                    if (_infiniteScrollEnabled)
                    {
                        cmi.visible = true;
                        continue;
                    }
                    if (cmi.pos >= _itemIndexLimitL + _oddItemCount && cmi.pos < _itemIndexLimitR + _oddItemCount)
                    {
                        cmi.visible = true;
                        continue;
                    }
                    cmi.visible = false;
                }
            }
        }

        void CompositionTarget_Rendering(object sender, EventArgs e)
        {
            render();
        }

        protected void render()
        {
            CurveMenuItem cmi;
            double pos;
            double index;
            ItemPosition position;
            List<CurveMenuItem> listL = new List<CurveMenuItem>();
            List<CurveMenuItem> listR = new List<CurveMenuItem>();
            for (var i = 0; i < _itemCount; i++)
            {
                cmi = _screenObjectList[i] as CurveMenuItem;
                pos = cmi.pos - _currentPosition;
                index = 0;
                if (pos < -0.5)
                {
                    cmi.pos = cmi.pos + _itemCount; 
                    if (cmi.IsInit)
                    {
                        cmi.MyItemData = itemDataList[_tailItemIndex];
                    }
                    _headItemIndex++;
                    if (_headItemIndex >= itemDataList.Count)
                    {
                        _headItemIndex = _headItemIndex - itemDataList.Count;
                    }
                    _tailItemIndex++;
                    if (_tailItemIndex >= itemDataList.Count)
                    {
                        _tailItemIndex = _tailItemIndex - itemDataList.Count;
                    }
                }
                else if (pos > (_itemCount - 0.5))
                {
                    cmi.pos = cmi.pos - _itemCount;
                    if (cmi.IsInit)
                    {
                        cmi.MyItemData = itemDataList[_headItemIndex];
                    }
                    _headItemIndex--;
                    if (_headItemIndex < 0)
                    {
                        _headItemIndex = itemDataList.Count + _headItemIndex;
                    }
                    _tailItemIndex--;
                    if (_tailItemIndex < 0)
                    {
                        _tailItemIndex = itemDataList.Count + _tailItemIndex;
                    }

                }
                if (cmi.IsInit)
                {
                    if (cmi.IsImgNull) { cmi.BuildUI(); }
                    position = getPosition(pos);
                    cmi.x = position.x;
                    cmi.y = position.y;
                    cmi.rotation = position.r;
                    cmi.alpha = position.a;
                    cmi.Scale = position.s;
                    cmi.RotationY = position.ry;
                }

                

                if (!_infiniteScrollEnabled)
                {
                    index = cmi.pos - _oddItemCount;
                    if (index < _itemIndexLimitR && index >= _itemIndexLimitL)
                    {
                        cmi.visible = true;
                    }
                    else
                    {
                        cmi.visible = false;
                    }
                }

                if (pos > _oddItemCount + 0.5)
                {
                    listR.Add(cmi);
                    continue;
                }
                listL.Add(cmi);
            }
            var nl = (from c in listL
                      orderby c.pos descending
                      select c);

            var nr = (from c in listR
                      orderby c.pos
                      select c);

            var t = 0;
            foreach (var c in nl)
            {
                _container.setChildIndex(c, t);

                t--;
            }

            t = -100;
            foreach (var c in nr)
            {
                _container.setChildIndex(c, t);

                t--;
            }




            if (nl.Count() > 0)
            {
                _currentItem = nl.ElementAt(0) as CurveMenuItem;
                if (_currentItem.MyItemData != null)
                {
                    _currentItemIndex = _currentItem.MyItemData.id;
                }
                CurrItemData = _currentItem.MyItemData;
            }
        }

        private ItemPosition getPosition(double index)
        {
            ItemPosition ip = new ItemPosition() { s = 1, r = 0, a = 1 };

            if (index < TIME_LIMIT_L)
            {
                ip.r = index * SIDE_ROTATION;
                ip.s = _itemScaleRatio * (TIME_LIMIT_L - index) / TIME_LIMIT_L + index / TIME_LIMIT_L;
            }
            else if (index >= TIME_LIMIT_R)
            {
                ip.r = (TIME_LIMIT_L + index - TIME_LIMIT_R) * SIDE_ROTATION + 2 * MIDDLE_ROTATION;
                ip.s = _itemScaleRatio * (index - TIME_LIMIT_R) / TIME_LIMIT_L + ((_itemCount - 1) - index) / TIME_LIMIT_L;
            }
            else
            {
                ip.r = TIME_LIMIT_L * SIDE_ROTATION + (index - TIME_LIMIT_L) * MIDDLE_ROTATION;
            }

            ip.r = (_curvature < 0) ? -ip.r : ip.r;
            ip.x = BASE_RADIUS * Math.Sin(ip.r);
            ip.y = (-BASE_RADIUS) * Math.Cos(ip.r);

            if (_curvature == 0)
            {
                ip.y = 0;
                if (index <= TIME_LIMIT_L)
                {
                    ip.x = (-_middleItemDistance) * 0.5 - (TIME_LIMIT_L - index) * _middleItemDistance * 0.5;
                }
                else if (index >= TIME_LIMIT_R)
                {
                    ip.x = _middleItemDistance * 0.5 + (index - TIME_LIMIT_R) * _itemDistance * 0.5;
                }
                else
                {
                    ip.x = (index - _oddItemCount) * _middleItemDistance * 0.5;
                }
            }

            if (index < _oddItemCount && index > TIME_LIMIT_L)
            {
                ip.s = (index - TIME_LIMIT_L) * (_middleItemScale - 1) + 1;
            }
            else if (index > _oddItemCount && index < TIME_LIMIT_R)
            {
                ip.s = (TIME_LIMIT_R - index) * (_middleItemScale - 1) + 1;
            }
            else if (index == _oddItemCount)
            {
                ip.s = _middleItemScale;
            }



            if (index > _oddItemCount)
            {
                ip.ry = max_roationy;
            }
            else
            {
                ip.ry = -max_roationy;
            }
            if (index > _oddItemCount && index < TIME_LIMIT_R)
            {
                ip.ry = (index - _oddItemCount) * max_roationy;
            }
            else if (index < _oddItemCount && index > TIME_LIMIT_L)
            {
                ip.ry = (index - _oddItemCount) * max_roationy;
            }
            else if (index == _oddItemCount)
            {
                ip.ry = 0;
            }

            if (index < _oddItemCount * 0.5)
            {
                ip.a = index / (_oddItemCount * 0.5) + _itemAlpha;
            }
            else if (index > (_itemCount - 1) - _oddItemCount * 0.5)
            {
                ip.a = ((_itemCount - 1) - index) / (_oddItemCount * 0.5) + _itemAlpha;
            }



            if (_curvature < 0)
            {
                ip.r = ip.r / Math.PI * 180 + 180;
            }
            else
            {
                ip.r = ip.r / Math.PI * 180;
            }

            return ip;
        }


        Tween<double> tween = null;
        protected void moveToItem(double index)
        {
            double time1;
            double time2;
            if (!_infiniteScrollEnabled)
            {
                if (index < _itemIndexLimitL)
                {
                    index = _itemIndexLimitL;
                }
                if (index >= _itemIndexLimitR) { }
            }
            if ((_itemIndexLimitR - 1) > _currentPosition)
            {
                _direction = 0;
            }
            else
            {
                _direction = 2;
            }

            time1 = _transitionTime / _oddItemCount;
            time2 = time1 * Math.Abs(index - _currentPosition);
            if (time2 > _transitionTime)
            {
                time2 = _transitionTime;
            }

            tween = Tweener<double>.CreateTween(this, CurveMenuPanel.CurrentPositionProperty, Expo.EaseOut, _currentPosition, index, TimeSpan.FromSeconds(time2));
        }
    }
}
